package com.elder.business.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.elder.business.domain.*;
import com.elder.business.mapper.*;
import com.elder.business.service.IOrderInfoService;
import com.elder.common.core.domain.AjaxResult;
import com.elder.common.core.page.TableDataInfo;
import com.elder.common.core.redis.RedisCache;
import com.elder.common.enums.OrderStatus;
import com.elder.common.utils.*;
import com.elder.common.utils.bean.BeanUtils;
import com.elder.common.utils.uuid.SnowGenerator;
import com.elder.common.utils.uuid.UUID;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Slf4j
@Service
public class OrderInfoServiceImpl implements IOrderInfoService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private ElderlyInfoMapper elderlyInfoMapper;
    @Autowired
    private ApartmentRoomInfoMapper apartmentRoomInfoMapper;
    @Autowired
    private ApartmentDictMapper apartmentDictMapper;
    @Autowired
    private NurseContentMapper nurseContentMapper;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ReceptionNoticeServiceImpl receptionNoticeService;
    @Autowired
    private OrderStatisticsServiceImpl orderStatisticsService;
    @Autowired
    private OrderStatisticsMapper orderStatisticsMapper;
    @Autowired
    private ElderServiceMapper elderServiceMapper;

    private final static String ORDER_INFO_KEY = "NO_PAY_ORDER";

    // 在每天凌晨0点触发定时任务
    @Scheduled(cron = "0 0 0 * * *")
    public void clearOrderInfo(){
        Long expirationTime = DateUtils.getTimestamp24HoursAgo();
        List<Long> orderIds = orderInfoMapper.getNoPassOrderList(expirationTime);
        if(CollectionUtils.isNotEmpty(orderIds)){
            orderInfoMapper.delorderInfo(orderIds);
        }
    }
    @Override
    @Transactional
    public Integer addOrderInfo(OrderInfoDTO orderInfo) {
        OrderInfo order = new OrderInfo();
        BeanUtils.copyProperties(orderInfo, order);
        if(Objects.isNull(orderInfo.getOrderId())) {
            order.setOrderId(SnowGenerator.getId());
        }
        order.setRoomPriceId(LongUtils.str2Long(orderInfo.getRoomPriceId()));
        order.setLiveTime(DateUtils.getTargetDateSeconds(orderInfo.getLiveTime()));
        String serviceIds = StringNewUtils.isEmpty(orderInfo.getProjectIds())?orderInfo.getServiceIds():orderInfo.getProjectIds();
        order.setServiceIds(serviceIds);
        if(Objects.isNull(orderInfo.getOrderStatus())) {
            order.setOrderStatus(OrderStatus.NO_PAY.getValue());
        }
        order.setLiveTime(DateUtils.getTargetDateSeconds(orderInfo.getLiveTime()));
        order.setOrderTime(DateUtils.getLongTime());
        order.setLiveMonth(orderInfo.getLiveMonth());
        orderInfoMapper.insertOrderInfo(order);
        return 1;
    }

    @Override
    public TableDataInfo getOrderInfoList(String elderName, String orderTime, Integer pageNum, Integer pageSize) {
        Long startTime = null;
        Long endTime = null;
        if(!StringUtils.isEmpty(orderTime)){
            Long time = DateUtils.getTargetDateSeconds(orderTime);
            startTime = DateUtils.getDayStartTime(time);
            endTime = DateUtils.getDayEndTime(time);
        }
        PageHelper.startPage(pageNum,pageSize);
        List<OrderInfo> list = orderInfoMapper.getOrderInfoList(elderName,startTime,endTime);
        PageInfo<OrderInfo> pageInfo = new PageInfo<>(list);
        List<OrderInfo> orderInfoList = pageInfo.getList();
        //获取项目id
        Set<Long> projectIds = new HashSet<>();
        for(OrderInfo orderInfo : orderInfoList){
            List<String> serviceIds = Arrays.asList(orderInfo.getServiceIds().split(","));
            for(String serviceId : serviceIds){
                projectIds.add(LongUtils.str2Long(serviceId));
            }
        }
        List<Long> longList = projectIds.stream().collect(Collectors.toList());
        List<NurseContent> nurseContentList = nurseContentMapper.getNurseContentList(longList);
        Map<Long, String> nurseMap = nurseContentList.stream().collect(Collectors.toMap(NurseContent::getNurseId, NurseContent::getNurseName));
        Map<Integer, String> codeMap = apartmentDictMapper.getApartmentDictInfo(1).stream().collect(Collectors.toMap(ApartmentDict::getCode, ApartmentDict::getName));
        //住戶信息
        List<Long> elderIds = orderInfoList.stream().map(OrderInfo::getElderId).distinct().collect(Collectors.toList());
        Map<Long,String> elderMap = CollectionUtils.isEmpty(elderIds)?new HashMap<>():
                elderlyInfoMapper.getElderInfoByElderIds(elderIds)
                .stream().collect(Collectors.toMap(ElderlyInfo::getElderId,ElderlyInfo::getElderName));
        List<JSONObject> orderInfoDTOList = null;
        if(CollectionUtils.isNotEmpty(orderInfoList)){
            orderInfoDTOList = orderInfoList.stream().map(v -> {
                JSONObject obj = new JSONObject();
                obj.put("orderId",StringNewUtils.long2Str(v.getOrderId()));
                obj.put("roomPriceId",StringNewUtils.long2Str(v.getRoomPriceId()));
                obj.put("totalAmount",v.getTotalAmount());
                obj.put("roomType",codeMap.get(v.getRoomType()));
                obj.put("elderId",StringNewUtils.formatStr(v.getElderId()));
                obj.put("elderName",elderMap.get(v.getElderId()));
                obj.put("liveTime",DateUtils.dateStr(v.getLiveTime()));
                obj.put("orderTime",DateUtils.dateStrMIAO(v.getOrderTime()));
                StringBuffer stringBuffer = new StringBuffer();
                if(!StringNewUtils.isEmpty(v.getServiceIds())) {
                    Arrays.asList(v.getServiceIds().split(",")).forEach(item->{
                        stringBuffer.append(nurseMap.get(LongUtils.str2Long(item))+",");
                    });
                    stringBuffer.substring(stringBuffer.length() - 1);
                }
                obj.put("nurseContent",stringBuffer);
                obj.put("orderStatus",v.getOrderStatus());
                obj.put("notes",v.getNotes());
                return obj;
            }).collect(Collectors.toList());
        }
        TableDataInfo data = new TableDataInfo();
        data.setCode(200);
        data.setTotal(pageInfo.getTotal());
        data.setRows(orderInfoDTOList);
        return data;
    }

    @Override
    public JSONObject getOrderInfoById(Long orderId) {
        return null;
    }

    /***
     * @description 创建订单存入redis
     * @param orderInfo
     * @return String
     * @author zyk
     * @date 2024/3/9 21:10
     */
    @Override
    @Transactional
    public JSONObject createOrderInfo(OrderInfoDTO orderInfo) {
        //订单号
        Long orderRedisHxId = SnowGenerator.getId();
        String projectIds = orderInfo.getProjectIds();
        List<Long> longList = Arrays.asList(projectIds.split(","))
                .stream().map(Long::parseLong).collect(Collectors.toList());
//        List<Long> longList = Arrays.stream(projectIds).map(Long::parseLong).collect(Collectors.toList());
        List<NurseContent> contentList = nurseContentMapper.getNurseContentList(longList);
        ElderlyInfo info = Objects.isNull(orderInfo.getElderId())?new ElderlyInfo():elderlyInfoMapper.getElderInfoByElderId(orderInfo.getElderId());
//        ApartmentRoomPrice roomPrice = apartmentRoomInfoMapper.getRoomPriceInfoByPriceId(LongUtils.str2Long(orderInfo.getRoomPriceId()));
        JSONObject obj = new JSONObject();
        obj.put("orderId",StringNewUtils.long2Str(orderRedisHxId));
        obj.put("customerName",info.getElderName());
        obj.put("liveTime",StringNewUtils.formatStr(orderInfo.getLiveTime()));
        obj.put("notes",orderInfo.getNotes());
        obj.put("roomPriceId", StringNewUtils.formatStr(orderInfo.getRoomPriceId()));
        obj.put("roomName", orderInfo.getRoomName());
        obj.put("roomPrice",orderInfo.getRoomPrice());
        obj.put("nurseContent",contentList.stream().map(v-> {
            JSONObject o = new JSONObject();
            o.put("nurseId",StringNewUtils.long2Str(v.getNurseId()));
            o.put("nurseName",v.getNurseName());
            o.put("nursePrice",v.getNursePrice());
            return o;
        }).collect(Collectors.toList()));
        obj.put("totalAmount",orderInfo.getTotalAmount());

        redisCache.setHashDataWithExpiration(ORDER_INFO_KEY,StringNewUtils.long2Str(orderRedisHxId),obj.toJSONString(),1440);
        //异步执行添加订单
        CompletableFuture.runAsync(() -> {
            orderInfo.setOrderId(orderRedisHxId);
            addOrderInfo(orderInfo);
        });
        return obj;
    }

    /***
     * @description  支付订单
     * @param orderId
     * @return AjaxResult
     * @author zyk
     * @date 2024/3/10 0:39
     */
    @Override
    @Transactional
    public AjaxResult updateOrderStatus(String orderId) {
//        Object value = redisCache.getCacheMapValue(ORDER_INFO_KEY, orderId);
//        if(Objects.isNull(value)){
//            return AjaxResult.error("订单不存在或已失效,请重新编辑");
//        }
//        redisCache.deleteCacheMapValue(ORDER_INFO_KEY,orderId);
        orderInfoMapper.updateOrderPayStatus(LongUtils.str2Long(orderId));
        CompletableFuture.runAsync(() -> {
            try {
                OrderInfo orderInfo = orderInfoMapper.selectOrderInfoByOrderId(LongUtils.str2Long(orderId));
                List<ElderService> serviceList = new ArrayList<>();
                Arrays.asList(orderInfo.getServiceIds().split(",")).forEach((item) ->{
                    ElderService elderService = new ElderService();
                    elderService.setId(SnowGenerator.getId());
                    elderService.setElderId(orderInfo.getElderId());
                    elderService.setDuration(orderInfo.getLiveMonth());
                    elderService.setNurseId(LongUtils.str2Long(item));
                    elderService.setCreateTime(DateUtils.getLongTime());
                    elderService.setCreateUserId(null);
                    serviceList.add(elderService);
                });
                elderServiceMapper.insertElderServiceList(serviceList);
                if(Objects.nonNull(orderInfo.getCustomerName())){
                    ApartmentRoomInfo roomInfo = apartmentRoomInfoMapper.getApartmentRoomInfoByRoomId(orderInfo.getRoomId());
                    ReceptionNotice notice = new ReceptionNotice();
                    notice.setOrderId(orderInfo.getOrderId());
                    notice.setMemberId(Objects.isNull(roomInfo)?null:roomInfo.getNurseId());
                    notice.setOrderTime(orderInfo.getOrderTime());
                    notice.setElderName(orderInfo.getCustomerName());
                    notice.setOrderNotes(orderInfo.getNotes());
                    notice.setLiveTime(orderInfo.getLiveTime());
                    notice.setRoomType(StringNewUtils.int2Str(orderInfo.getRoomType()));
                    notice.setNurseContents(orderInfo.getServiceIds());
                    notice.setLiveMonth(orderInfo.getLiveMonth());
                    receptionNoticeService.insertReceptionNotice(notice);
                }
                //全量统计金额
                Long monthStartTime = DateUtils.getMonthStartTime();
                Long monthEndTime = DateUtils.getMonthEndTime();
                //当月订单数量
                OrderInfo orders = orderInfoMapper.getCurrentMonthOrders(monthStartTime, monthEndTime);
                orderStatisticsService.updateOrderStatisticsInfo(monthStartTime,orders.getCustomerName(),orders.getTotalAmount());
                LogUtils.getBlock("order StatisticsInfo  success");
            }catch (Exception e){
                log.error("order  error",e);
            }
        });
        return AjaxResult.success();
    }
}
